package org.xx.armory.docs;


import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static org.xx.armory.commons.Validators.notBlank;

/**
 * 模板数据上下文, 包含了使用模板输出时使用的数据。
 *
 * @author Haart
 */
public final class TemplateContext
        implements Iterable<String> {
    private final Map<String, Object> data;

    /**
     * 构造模板上下文。
     */
    public TemplateContext() {
        this.data = new HashMap<>();
    }

    /**
     * 构造模板上下文。
     *
     * @param map
     *         模板上下文包含的数据。
     */
    public TemplateContext(
            Map<String, Object> map
    ) {
        this.data = map == null ? new HashMap<>() : new HashMap<>(map);
    }

    /**
     * 将键正规化。
     *
     * @param key
     *         键名。
     * @return 正规化并且转为小写的键名。
     * @throws NullPointerException
     *         如果参数{@code key}是{@code null}。
     * @throws IllegalArgumentException
     *         如果参数{@code key}只包含空白字符。
     */
    private static String ensureKey(
            String key
    ) {
        return notBlank(key, "key").trim().toLowerCase();
    }

    public final Object get(
            String key
    ) {
        return this.data.get(ensureKey(key));
    }

    public final String getString(
            String key
    ) {
        final Object value = this.data.get(ensureKey(key));
        return value != null ? (String) value : "";
    }

    public final Object get(
            String key,
            int index
    ) {
        final Object value = this.data.get(ensureKey(key));
        return Array.get(value, index);
    }

    public final String getString(
            String key,
            int index
    ) {
        final Object arrayValue = this.data.get(ensureKey(key));
        final Object itemValue = Array.get(arrayValue, index);
        return itemValue != null ? (String) itemValue : "";
    }

    public final int getArraySize(
            String key
    ) {
        final Object arrayValue = this.data.get(ensureKey(key));
        if (arrayValue != null && arrayValue.getClass().isArray()) {
            return Array.getLength(arrayValue);
        } else {
            return -1;
        }
    }

    public final Object put(
            String key,
            Object value
    ) {
        return this.data.put(ensureKey(key), value);
    }

    public final Object put(
            String key,
            int index,
            Object value
    ) {
        final Object arrayValue = this.data.get(ensureKey(key));
        final Object itemValue = Array.get(arrayValue, index);
        Array.set(arrayValue, index, value);
        return itemValue;
    }

//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public int size() {
//        return this.data.size();
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public boolean isEmpty() {
//        return this.data.isEmpty();
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public boolean containsName(Object key) {
//        notNull(key, "key");
//
//        return this.data.containsName(ensureKey(key.toString()));
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public boolean containsValue(final Object value) {
//        return this.data.containsValue(value);
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public Object get(final Object key) {
//        final Object obj = this.data.get(ensureKey(key.toString()));
//        return obj == null ? "" : obj;
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public Object put(
//            String key,
//            Object value
//    ) {
//        return this.data.put(ensureKey(key), value);
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public Object remove(Object key) {
//        notNull(key, "key");
//
//        return this.data.remove(ensureKey(key.toString()));
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public void putAll(Map<? extends String, ?> m) {
//        this.data.putAll(m);
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public void clear() {
//        this.data.clear();
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public Set<String> keySet() {
//        return this.data.keySet();
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public Collection<Object> values() {
//        return this.data.values();
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public Set<java.util.Map.Entry<String, Object>> entrySet() {
//        return this.data.entrySet();
//    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterator<String> iterator() {
        return this.data.keySet().iterator();
    }
}
